package pl.edu.uj.tcs.blef.server;

import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map.Entry;

import pl.edu.uj.tcs.blef.protocol.AcceptRequestFactory;
import pl.edu.uj.tcs.blef.protocol.AcceptRequestHandler;
import pl.edu.uj.tcs.blef.protocol.BetRequestFactory;
import pl.edu.uj.tcs.blef.protocol.BetRequestHandler;
import pl.edu.uj.tcs.blef.protocol.CheckRequestFactory;
import pl.edu.uj.tcs.blef.protocol.CheckRequestHandler;
import pl.edu.uj.tcs.blef.protocol.JoinRequestFactory;
import pl.edu.uj.tcs.blef.protocol.JoinRequestHandler;
import pl.edu.uj.tcs.blef.protocol.KickRequestFactory;
import pl.edu.uj.tcs.blef.protocol.KickRequestHandler;
import pl.edu.uj.tcs.blef.protocol.MsgRequestFactory;
import pl.edu.uj.tcs.blef.protocol.MsgRequestHandler;
import pl.edu.uj.tcs.blef.protocol.NullRequestHandler;
import pl.edu.uj.tcs.blef.protocol.RejectRequestFactory;
import pl.edu.uj.tcs.blef.protocol.RejectRequestHandler;
import pl.edu.uj.tcs.blef.protocol.Request;
import pl.edu.uj.tcs.blef.protocol.RequestFactory;
import pl.edu.uj.tcs.blef.protocol.RequestHandler;
import pl.edu.uj.tcs.blef.protocol.SetNewDealRequestFactory;
import pl.edu.uj.tcs.blef.protocol.SetNewDealRequestHandler;
import pl.edu.uj.tcs.blef.protocol.SetNewGameRequestFactory;
import pl.edu.uj.tcs.blef.protocol.SetNewGameRequestHandler;
import pl.edu.uj.tcs.blef.protocol.ShowBetPoolRequestFactory;
import pl.edu.uj.tcs.blef.protocol.ShowBetPoolRequestHandler;
import pl.edu.uj.tcs.blef.protocol.ShowHandRequestFactory;
import pl.edu.uj.tcs.blef.protocol.ShowHandRequestHandler;
import pl.edu.uj.tcs.blef.protocol.ShowPlayersRequestFactory;
import pl.edu.uj.tcs.blef.protocol.ShowPlayersRequestHandler;
import pl.edu.uj.tcs.blef.protocol.UnknownRequestErrorFactory;

public final class TableRequestHeadquarters {
	private Table table;
	private static HashMap<RequestFactory, RequestHandler> factories;
	private static NullRequestHandler nullRequestHandler;
	private static UnknownRequestErrorFactory unknownRequestErrorFactory;
	
	public TableRequestHeadquarters(Table table){
		/* Error request factories */
		this.table = table;
		nullRequestHandler = new NullRequestHandler();
		unknownRequestErrorFactory = new UnknownRequestErrorFactory();
		
		/* Accepted request factories */
		factories = new HashMap<RequestFactory, RequestHandler>();
		factories.put(new AcceptRequestFactory(), new AcceptRequestHandler(table));
		factories.put(new RejectRequestFactory(), new RejectRequestHandler(table));
		factories.put(new KickRequestFactory(), new KickRequestHandler(table));
		factories.put(new JoinRequestFactory(), new JoinRequestHandler(table));
		factories.put(new SetNewGameRequestFactory(), new SetNewGameRequestHandler(table));
		factories.put(new SetNewDealRequestFactory(), new SetNewDealRequestHandler(table));
		factories.put(new ShowHandRequestFactory(), new ShowHandRequestHandler(table));
		factories.put(new ShowPlayersRequestFactory(), new ShowPlayersRequestHandler(table));
		factories.put(new ShowBetPoolRequestFactory(), new ShowBetPoolRequestHandler(table));
		factories.put(new MsgRequestFactory(), new MsgRequestHandler(table));
		factories.put(new BetRequestFactory(), new BetRequestHandler(table));
		factories.put(new CheckRequestFactory(), new CheckRequestHandler(table));
	}
	
	void parse(String message, Socket socket){
		for(Entry<RequestFactory, RequestHandler> e : factories.entrySet()){
			try { 
				Request request = e.getKey().parse(message, e.getValue());
				System.out.println("Accepted TABLE:" + socket.getLocalPort() + " request: " + message);
				request.getHandler().handle(request, socket);
				return;
			} catch(Exception ex){ }
		}
		
		/* Unknown request */
		try{
			Request unknownRequest = unknownRequestErrorFactory.build(null, nullRequestHandler);
			unknownRequest.send(new PrintWriter(socket.getOutputStream()));
		} catch (Exception e){ return; }
	}
}
